#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>


/*
int main()
{
  printf("begin.....\n");
  printf("begin.....\n");
  printf("begin.....\n");
  printf("begin.....\n");
  
  execl("/bin/ls", "ls", "-l", NULL);//必须以NULL结尾
  //当程序执行execl时，发生程序替换，当前进程的代码和数据就会被改写成execl调用的程序代码和数据,
  //程序替换是整体替换，不是局部替换，替完之后老的代码和数据都没有了，也就看不到end的执行了！
  
  //进程在被创建的时候，先创建PCB再加载代码和数据，需要的时候去调用

  printf("end.....\n");
  printf("end.....\n");
  printf("end.....\n");
  printf("end.....\n");
  return 0;
}
*/

int main()
{
  gid_t id = fork();

  if(id == 0)
  {
    printf("我是子进程:%d\n", getpid());
    //execl: 如果替换成功，不会有返回值，如果替换失败，一定有返回值 ==》如果失败了，必定返回 ==》 只要有返回值，就失败了
    //不用对该函数进行返回值判断，只要继续向后运行一定是失败的！
    //int ret = execl("/bin/lssss", "lsssss", "-al", NULL);//替换失败
    //execl("/bin/lssss", "lsssss", "-al", NULL);//替换失败
    //printf("进程替换失败\n");
    
    /////////////////////////////////////////////////////进程替换接口
    //execl("/bin/ls", "ls", "-a", "-l", NULL);
    //execl("./exe/otherpro", "otherpro", NULL);
    
    //execlp("otherpro", "otherpro", NULL);//第一个参数直接给可执行文件名，是在PATH中的路径下找该otherpr名字
    //execlp("ls", "ls","-l", "-a", "-n", NULL);
    
    //char* const myargv[] = {
    //  "-a", "-l", "-n", NULL
    //};
    //execv("/bin/ls", myargv);
    //execvp("ls", myargv);
    
    //char* myenv[] = {
    //  "MYENV=you can see me!", NULL
    //};
    //execle("./exe/otherpro", "otherpro", NULL, myenv);//myenv会覆盖式的传给子进程，就是用myenv（自定义的环境变量列表）将环境变量中的内容覆盖掉
    extern char **environ;
    putenv("MYENV=you can see me!");//在当前环境变量列表中添加自定义环境变量，并不会覆盖原来的
   // execle("./exe/otherpro", "otherpro", NULL, environ);
    
    char* const myargv[] = {
      "otherpro", NULL
    };
    execve("./exe/otherpro", myargv  , environ);
    exit(1);
  }
  sleep(1);

  int status = 0;
  waitpid(id, &status, 0);
  printf("我是父进程:%d exit code:%d\n", getpid(), WEXITSTATUS(status));
  return 0;
}
